package zcatt.examples.java.demos;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/*
 * 本例演示ThreadPoolExecutor的使用.
 * 素数的寻找
 */
public class Snippet003_ThreadPoolExecutor {

	public static void main(String[] args) {
		System.out.println("Snippet003_ThreadPoolExecutor start....");
		
		primeNumbers = Collections.synchronizedList(new LinkedList<Integer>()); 
		
		int start = 1000000;
		int len = 1000;
		
		//使用unbounded queue
		//自制threadFactory, 没有使用Executors便利
		ThreadPoolExecutor tpe = new ThreadPoolExecutor(
				4						//corePoolSize
				, 4						//maximumPoolSize, 对于unbounded queue无意义
				, 100						//keepAliveTime
				, TimeUnit.MILLISECONDS		//timeUnit
				, new LinkedBlockingQueue<Runnable>()	//workQueue. linkedBlockingQueue无上限, 故this tpe时unbounded queue.
				, new MyThreadFactory()				//threadFactory
				);
		
		for(int i = 0; i< len; i++)
		{
			tpe.execute(new PrimeNumberTask(start+i));				
		}
		
		//no new task will be accepted
		
		tpe.shutdown();
		
		//wait until all tasks are over 
		
		try {
			while(! tpe.awaitTermination(50, TimeUnit.MILLISECONDS))
			{
				System.out.println("Main thread waiting....");
			}
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}

		//output the result
		
		StringBuffer s = new StringBuffer("result= ");
		for(int i: primeNumbers)
		{
			s.append(i).append(", ");
		}

		System.out.println(s);
		System.out.println("Snippet003_ThreadPoolExecutor over");
		
	}

	static List<Integer> primeNumbers;	//保存找到的primeNumbers
	
	public static boolean isPrimeNumber(int num)
	{
		System.out.println("thread("+Thread.currentThread().getId()+"), check "+num);
		if(num == 1 || num == 2)
			return false;
		
		try {
			Thread.sleep(10);
		}
		catch(Exception e)
		{				
		}
		
		for(int i = 2; i <= num/2; i++)
		{
			if((num/i) *i == num)
				return false;
		}
		return true;			
	}
	
	public static class PrimeNumberTask implements Runnable
	{
		int num;
		public PrimeNumberTask(int num)
		{
			this.num = num;			
		}

		
		@Override
		public void run() {
			if(isPrimeNumber(num))
			{
				primeNumbers.add(num);
			}			
		}
		
	}
	
	public static class MyThreadFactory implements ThreadFactory
	{

		@Override
		public Thread newThread(Runnable r) {
			//ThreadGroup group = Thread.currentThread().getThreadGroup();
			return new Thread(r);
		}
		
	}
}
